package cn.fintecher.pangolin.service.business.web;

import cn.fintecher.pangolin.common.enums.*;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.BeanUtils;
import cn.fintecher.pangolin.entity.mysql.*;
import cn.fintecher.pangolin.service.business.model.request.*;
import cn.fintecher.pangolin.service.business.model.response.AssistCaseResponse;
import cn.fintecher.pangolin.service.business.model.response.ProcessApplicationResponse;
import cn.fintecher.pangolin.service.business.model.response.ProcessApproveResponse;
import cn.fintecher.pangolin.service.business.model.response.ProcessFlowNodesResponse;
import cn.fintecher.pangolin.service.business.repository.jparepository.AssistCaseRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.ProcessApplicationRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.ProcessApproverRepository;
import cn.fintecher.pangolin.service.business.service.BaseService;
import cn.fintecher.pangolin.service.business.service.CaseApplyManageService;
import com.querydsl.core.BooleanBuilder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author wangxiangdong
 * @Description 流程申请相关操作
 * @Date 2019/9/19 11:09
 **/
@RestController
@RequestMapping("/api/caseApplyManageController")
@Api(value = "申请相关操作", description = "申请相关操作")
@Slf4j
public class CaseApplyManageController {


    @Autowired
    private BaseService baseService;

    @Autowired
    private CaseApplyManageService caseApplyManageService;

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private ProcessApplicationRepository processApplicationRepository;

    @Autowired
    private ProcessApproverRepository processApproverRepository;

    @Autowired
    private AssistCaseRepository assistCaseRepository;

    @PostMapping("/caseApplyOperated")
    @ApiOperation(value = "申请操作", notes = "申请操作")
    public ResponseEntity caseApplyOperated(@RequestBody ProcessApplicationRequest request, @RequestHeader(value = "X-UserToken") String token) {
        caseApplyManageService.createProcessApplication(request, baseService.getUserByToken(token));
        return new ResponseEntity<>(null, HttpStatus.OK);
    }

    @GetMapping("/getProcessApproveMessage")
    @ApiOperation(value = "各类审批查询", notes = "各类审批查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query",
                    value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query",
                    value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity getProcessApproveMessage(Pageable pageable, ProcessApproveRequest processApproveRequest, @RequestHeader(value = "X-UserToken") String token) {
        UserModel userModel = baseService.getUserByToken(token);
        BooleanBuilder booleanBuilder = processApproveRequest.generateQueryBuilder();
        QProcessApprover qProcessApprover = QProcessApprover.processApprover;
        booleanBuilder.and(qProcessApprover.userId.eq(userModel.getId()).and(qProcessApprover.processFlowNode.isShow.eq(BaseSelect.YES))
                .and(qProcessApprover.processFlowNode.approvalStatus.eq(processApproveRequest.getApprovalStatus()))
        );
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(qProcessApprover.processFlowNode.processApplication.principalId.in(userModel.getPrincipalIds()));
        }
        if (Objects.equals(processApproveRequest.getApprovalStatus(), ApprovalStatus.WAIT_APPROVAL) && Objects.equals(processApproveRequest.getExportState(), ExportState.EXPORTED)) {
            Sort sort = new Sort(Sort.Direction.DESC, "processFlowNode.processApplication.operatorDate");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        } else if (Objects.equals(processApproveRequest.getApprovalStatus(), ApprovalStatus.WAIT_APPROVAL)) {
            Sort sort = new Sort(Sort.Direction.ASC, "processFlowNode.processApplication.applyDate");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        } else if (Objects.equals(processApproveRequest.getApprovalStatus(), ApprovalStatus.APPROVED_COMPLETED)) {
            Sort sort = new Sort(Sort.Direction.DESC, "processFlowNode.approvalTime");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        }
        Page<ProcessApproveResponse> processApplications = processApproverRepository.findAll(booleanBuilder, pageable).map(processApprover ->
                modelMapper.map(processApprover, ProcessApproveResponse.class)
        );
        return new ResponseEntity<>(processApplications, HttpStatus.OK);
    }

    @GetMapping("/getProcessFlowNodes")
    @ApiOperation(value = "根据申请id查询流程审批节点", notes = "根据申请id查询流程审批节点")
    public ResponseEntity<List<ProcessFlowNodesResponse>> getProcessFlowNodes(String processApplicationId, @RequestHeader(value = "X-UserToken") String token) {
        baseService.getUserByToken(token);
        ProcessApplication processApplication = processApplicationRepository.findById(processApplicationId).orElseThrow(() -> new BadRequestException(null, "", "application.is.not.found"));
        Set<ProcessFlowNode> processFlowNodes = processApplication.getProcessFlowNodes();
        List<ProcessFlowNodesResponse> processFlowNodesResponseList = new ArrayList<>();
        for (ProcessFlowNode processFlowNode : processFlowNodes) {
            ProcessFlowNodesResponse processFlowNodesResponse = new ProcessFlowNodesResponse();
            BeanUtils.copyPropertiesIgnoreNull(processFlowNode, processFlowNodesResponse);
            processFlowNodesResponse.setApproverNames(processFlowNode.getProcessApprovers().stream().map(ProcessApprover::getUserName).collect(Collectors.joining(",")));
            processFlowNodesResponseList.add(processFlowNodesResponse);
        }
        return new ResponseEntity<>(processFlowNodesResponseList, HttpStatus.OK);
    }

    @PostMapping("/caseApplyApprove")
    @ApiOperation(value = "审批操作", notes = "审批操作")
    public ResponseEntity caseApplyApprove(@RequestBody ApproveRequest request, @RequestHeader(value = "X-UserToken") String token) {
        caseApplyManageService.processApprove(request, baseService.getUserByToken(token));
        return new ResponseEntity<>(null, HttpStatus.OK);
    }


    @GetMapping("/getProcessApplicationByFlowType")
    @ApiOperation(value = "申请信息查询", notes = "申请信息查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query", value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query", value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query", value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<ProcessApplicationResponse>> getProcessApplicationByFlowType(ProcessApplcationRequest processApplcationRequest, Pageable pageable,
                                                                                            @RequestHeader(value = "X-UserToken") String token) {
        baseService.getUserByToken(token);
        Page<ProcessApplicationResponse> basicCaseApplyResponses = caseApplyManageService.getProcessApplicationByFlowType(processApplcationRequest, pageable);
        return new ResponseEntity<>(basicCaseApplyResponses, HttpStatus.OK);
    }


    @ApiOperation(value = "协催管理查外访案件", notes = "协催管理查外访案件")
    @GetMapping("/searchAssistCase")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query",
                    value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query",
                    value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<AssistCaseResponse>> searchAssistCase(AssistCaseSearchRequest request, Pageable pageable, @RequestHeader(value = "X-UserToken") String token) {
        log.info("search wait distributed case");
        UserModel userModel = baseService.getUserByToken(token);
        BooleanBuilder booleanBuilder = request.generateQueryBuilder();
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(QAssistCase.assistCase.principalId.in(userModel.getPrincipalIds()));
        }
        if (Objects.equals(request.getAssistStatus(), AssistStatus.ASSIST_WAIT_ASSIGN)) {
            Sort sort = new Sort(Sort.Direction.ASC, "visitTimeStart");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        } else if (Objects.equals(request.getAssistStatus(), AssistStatus.ASSIST_COLLECTING)) {
            Sort sort = new Sort(Sort.Direction.ASC, "visitTimeStart", "operatorTime");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        } else if (Objects.equals(request.getAssistStatus(), AssistStatus.ASSIST_COMPLETED)) {
            Sort sort = new Sort(Sort.Direction.DESC, "visitTimeStart");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        } else if (Objects.equals(request.getAssistStatus(), AssistStatus.ASSIST_CANCEL)) {
            Sort sort = new Sort(Sort.Direction.DESC, "visitTimeEnd");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        }
        Page<AssistCase> assistCasePage = assistCaseRepository.findAll(booleanBuilder, pageable);
        Page<AssistCaseResponse> assistCasesResponsePage = assistCasePage.map(assistCase -> modelMapper.map(assistCase, AssistCaseResponse.class));
        return ResponseEntity.ok().body(assistCasesResponsePage);
    }

    @PostMapping("/approveByBatch")
    @ApiOperation(value = "批量审批", notes = "批量审批")
    public ResponseEntity approveByBatch(@RequestBody ApproveByBatchModel approveByBatchModel, @RequestHeader(value = "X-UserToken") String token) {
        caseApplyManageService.approveByBatch(approveByBatchModel, baseService.getUserByToken(token));
        return ResponseEntity.ok().build();
    }


    @GetMapping("/getLetterPrint")
    @ApiOperation(value = "信函打印查询", notes = "信函打印查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query",
                    value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query",
                    value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity getLetterPrint(Pageable pageable, LetterPrintRequest letterPrintRequest, @RequestHeader(value = "X-UserToken") String token) {
        UserModel userModel = baseService.getUserByToken(token);
        BooleanBuilder booleanBuilder = letterPrintRequest.generateQueryBuilder();
        QProcessApprover qProcessApprover = QProcessApprover.processApprover;
        booleanBuilder.and(qProcessApprover.userId.eq(userModel.getId())
                .and(qProcessApprover.processFlowNode.processApplication.approvalStage.eq(ApprovalStage.APPROVED_PASS))
        );
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(qProcessApprover.processFlowNode.processApplication.principalId.in(userModel.getPrincipalIds()));
        }
        if (Objects.equals(letterPrintRequest.getExportState(), ExportState.WAIT_EXPORT)) {
            Sort sort = new Sort(Sort.Direction.ASC, "processFlowNode.processApplication.applyDate");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        } else if (Objects.equals(letterPrintRequest.getExportState(), ExportState.EXPORTED)) {
            Sort sort = new Sort(Sort.Direction.DESC, "processFlowNode.processApplication.applyDate");
            pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
        }
        Page<ProcessApproveResponse> processApplications = processApproverRepository.findAll(booleanBuilder, pageable).map(processApprover ->
                modelMapper.map(processApprover, ProcessApproveResponse.class)
        );
        return new ResponseEntity<>(processApplications, HttpStatus.OK);
    }

    @PostMapping("/changePrintStatus")
    @ApiOperation(value = "", notes = "信函打印状态更改")
    public ResponseEntity<Void> changePrintStatus(@RequestBody ChangePrintStatusRequest changePrintStatusRequest) {
        caseApplyManageService.changePrintStatus(changePrintStatusRequest);
        return ResponseEntity.ok().build();
    }


}
